#pragma once

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "CH58x_common.h"
#include <string.h>
#include "task_dbg.h"
#include "share.h"

extern char cat1_sw_ver[ZQ_VER_MAX_LEN];		// 接收cat1版本号, 类似"1.0.2.00"
extern int IsCat1ReadyOff;

// 定义长按键重复发送键值的周期，ms
#define KEY_SCAN_REPEAT_INTERVAL 	(500)

// 任务轮询周期  50ms
#define TASK_PERIOD 50						
// define global event base number
#define ZY_EVENT_KEY	0x10
#define ZQ_EVENT_IOT	0x20

#define UART0_RX_BUF_SIZE (512+32)	// 最大情况出现在OTA, 一帧大小为5+6+512
#define UART1_RX_BUF_SIZE (512+32)	// 最大情况出现在OTA, 一帧大小为5+6+512
#define UART2_RX_BUF_SIZE (512+32)	// 最大情况出现在OTA, 一帧大小为5+6+512

// define ftm data flash address
#define FTM_DEV_INFO_FLASH_ADDR (0x00000000 + EEPROM_PAGE_SIZE * 0)

typedef struct {
	int r_pos;		// ring buf read pos
	int len;		// ring data len
	int size;		// ring buffer size
	uint8_t data[0];// ring buf
} ZqRingBuf;


// ## general macro definition ----------------------------------------------------------------------------------------
// IO related macro
#define ZyGPIO_A(io)	(1 << io)
#define ZyGPIO_B(io)	((1 << io) | 0x80000000)
#define ZyGPIO_NA		(0)
#define ZyGPIO_MASK		(0x7fffffff)
#define ZyIsGPIOValid(io)	((io & ZyGPIO_MASK) != 0)

// simply splice multi bytes by big edian
#define ZyGetValue_2B(p) (((*(uint8_t *)(p)) << 8) | (*((uint8_t *)(p)+1)))
#define ZyGetValue_3B(p) (((*(uint8_t *)(p)) << 16) | ((*((uint8_t *)(p)+1)) << 8) | (*((uint8_t *)(p)+2)))
#define ZyGetValue_4B(p) (((*(uint8_t *)(p)) << 24) | ((*((uint8_t *)(p)+1)) << 16) | ((*((uint8_t *)(p)+2)) << 8) | (*((uint8_t *)(p)+3)))

typedef enum {
	CTRL_STATE_OFF = 0x00,			// 控制器状态-关闭
	CTRL_STATE_NORMAL,				// 控制器状态-正常开机
	CTRL_STATE_LP_PRE,				// 控制器状态-低功耗前期
	CTRL_STATE_LP,					// 控制器状态-低功耗
	CTRL_STATE_LP_24H,				// 控制器状态-低功耗 每24H激活上报状态
	CTRL_STATE_SA,					// 生产半制
	CTRL_STATE_FA,					// 生产全制
	CTRL_STATE_RESET,				// 软件控制重启	
	CTRL_STATE_RESET_SELF,			// 软件控制重启控制器本身，不重启cat1	
	CTRL_STATE_MODE_SWITCH,			// 软件控制切换模式，不重启cat1	
	CTRL_STATE_RESET_HD,			// 软件控制重启, 正真的硬件级别重启	
	CTRL_STATE_DIAG_1004,			// 1004 temperature diagnostic mode
}ZyCtrlState;


// 系列原子操作函数
extern void AtomicClear32(volatile uint32_t *addr);
extern void AtomicAnd32(volatile uint32_t *addr, uint32_t val);
// 系列GPIOA/B操作函数
extern void GPIO_ModeCfg(uint32_t gpio, GPIOModeTypeDef mode);
extern void GPIO_ResetBits(uint32_t gpio);
extern void GPIO_SetBits(uint32_t gpio);
extern void GPIO_InverseBits(uint32_t gpio);
extern uint32_t GPIO_ReadPortPin(uint32_t gpio);
extern void GPIO_ITModeCfg(uint32_t gpio, GPIOITModeTpDef mode);
extern void GPIO_EnableIRQ(uint32_t gpio, bool en);

// general structure definition ----------------------------------------------------------------------------------------
typedef struct {
	unsigned short id;
	unsigned short param1;	
	size_t param2;
} ZqMessage;

// M0 flash local config file structure
typedef struct {
	char f1;				// valid flag = 'Z'
	char f2;				// valid flag = 'Q'
	char f3; 				// valid flag = 'M'
	uint8_t ver;			// this file format version
	char model[16];			// device model name
	uint8_t ctrl_switch;	// controller switch
	uint8_t ctrl_mode;		// controller run mode
	uint8_t res[2 + 8];		// controller run mode last
} ZqmCfgFile;
extern ZqmCfgFile zqm_cfg;

#pragma pack(4)	// #pragma pack(1) risc-v5 cpu 内存访问要对齐地址（按照数据类型对齐），所以不要随意压缩，除非成员全是byte，或者手动调整 
typedef struct {
	uint8_t ble_uuid[16];			// ble uuid
	uint8_t ble_major[2];
	uint8_t ble_minor[2];
	uint8_t ble_mac[6];
	int8_t ftm_vol_delta;       	// 功率计电压校正系数
	int8_t ftm_cur_delta;   	    // 功率计电流校正系数
	int8_t ftm_pow_delta; 	      	// 功率计功率校正系数
	uint8_t run_in_ftm; 			// 是否运行在生产模式下

	uint8_t m0_start_cause;			// 本次M0启动原因 - 参见 START_CAUSE_M0
	uint8_t cat1_start_cause;		// 本次Cat1启动原因 - 参见 START_CAUSE_CAT1
    uint32_t m0_run_time; 			// m0本次累计运行时间(包括睡眠时间), 秒
	int door1_count;				// 门1开关计数/24h
	int human_count;				// 人流计算/24h
} M0DiagnosticInfo;
#pragma pack()
extern M0DiagnosticInfo m0_diag;

typedef struct {
	uint32_t uart0_tx;			// UART0 TX
	uint32_t uart0_rx;			// UART0 RX
	uint32_t uart1_tx;			// UART1 TX
	uint32_t uart1_rx;			// UART1 RX
	uint32_t uart2_tx;			// UART2 TX
	uint32_t uart2_rx;			// UART3 RX
	uint32_t uart3_tx;			// UART3 TX
	uint32_t uart3_rx;			// UART3 RX
	uint32_t periph_pow;		// 外设电源控制
	uint32_t cat1;				// cat1(通讯模块)控制脚
	uint32_t motor;				// 压机控制脚
	uint32_t fan;				// 蒸发风机控制脚
	uint32_t condenser_fan;		// 冷凝风机控制脚
	uint32_t heater;			// 制热控制脚
	uint32_t light;   			// 照明控制脚
	uint32_t melt;   			// 化霜加热/电磁阀控制脚
	uint32_t buzzor;			// 蜂鸣器
	uint32_t det_12v;			// 电源侦测脚
	uint32_t det_sys_switch;   	// 系统开关侦测脚
	uint32_t det_door1;			// 门1侦测脚
	uint32_t det_door2;			// 门2侦测脚
	uint32_t det_human;			// 红外人流侦测脚
	uint32_t dis_dio;			// 显示驱动spi数据线
	uint32_t dis_clk;			// 显示驱动模拟spi时钟线
	uint32_t dis_stb;			// 显示驱动使能脚
	uint32_t ntc1_adc;     		// 传感器1
	uint32_t ntc2_adc;     		// 传感器2
	uint32_t batt_adc;     		// 电池电压侦测脚
	uint32_t batt_chrg;			// 电池侦测/充电脚
	uint32_t batt_stdby;     	// 电池待机脚
} ZyIOsDefTable;
extern ZyIOsDefTable zy_ios;

// all controller states
typedef struct {
	short d_temp; 				// 显示温度
	short m_temp; 				// 测量温度
	short load_vol;				// 负载电压
	short load_cur;				// 负载电流
	short load_pow;				// 负载功率
	short vbat;					// 电池电压 mv, 0 - 4200, =NUM_INVALID_WORD 表示无电池

	uint8_t alarm;				// 报警
	uint8_t fan_state;			// 风机工作状态
	uint8_t light_state;		// 照明灯开关
	uint8_t heater_state;		// 加热器启停状态

	uint8_t ble;				// 蓝牙工作状态
	uint8_t _4g;				// 4G工作状态, ZyMode4g
	uint8_t wifi;				// "wifi",
	uint8_t _4g_strength;		// "4G信号强度",
	// 控制器state
	uint8_t ctrl_mode;			// 控制器工作模式: ZqmtrlMode
	uint8_t ctrl_state;			// 控制器工作状态: 0-关闭, 1-开启, 2-低功耗前期, 3-低功耗, 4-24H上报; ZyCtrlState
	uint8_t ctrl_switch;		// 开关状态, on/off - 1/0; b0: remote_switch, b1: hard_switch, b2: soft_switch, 所以ctrl_switch=0x07表示开关全开
	// 压机state
	uint8_t comp_mode;			// 压机运行模式, 参见ZqCompModeEnum, 可能多个mode组合，但是当前实际按优先级运行
	uint8_t comp_state;			// 压机预计启停状态, 参见ZqCompStateEnum
	uint8_t temp_reach_region;	// 温度到达过TS+-2区间, 0-未达过, 1-到达过
	uint16_t power_up_6h;		// 上电6小时计时

	int comp_on_timer;			// 压机本次运行时间
	int comp_on_timer_acc;		// 压机累计运行时间
	int comp_off_timer;			// 压机关机时间
	int sensor_fault_on;		// 故障制冷开机时间 c3
	int sensor_fault_off;		// 故障制冷关机时间 c4
	int comp_cc;				// 强制开机时间

	// 除霜state
	//uint8_t defrost_state;	// 除霜工作状态
	int defrost_timer;			// 除霜运行时间
	short defrost_d_temp; 		// 除霜传感器显示温度
	short defrost_m_temp; 		// 除霜传感器测量温度
	int defrost_drain_timer;	// 除霜排水时间
	int defrost_lock_timer;		// 除霜后温度锁定计时

	int door1_timer;            // 门1开累计计时s, <= 0: 门关, 由数据采样模块负责
	int door1_count;			// 门1开累计计次, 由数据采样模块负责    
	int humman;					// 人流量累计计数
	// 温度报警延迟计时
	int alarm_ad_timer;
	// cat1 心跳计时
	uint32_t cat1_heart;
} ZqMcuStates;
extern ZqMcuStates zy_st;




//  some share global variable declare -----------------------------------------------------------------------------------------------
extern unsigned long long zq_last_tick;             // 辅助计时器计算用。其他地方不要用。注：上电计时用SysTick->CNT, 系统tick计数器，单位1ms。
extern volatile unsigned int zq_timer_50ms; 	    // 主任务循环前开始计时, 50ms精度, 单位1ms, 基于高速时钟。主循环前会清零, 约49天多会溢出, 溢出后跳过0重新由TASK_PERIOD开始, 可以用来=0判断初始化。是大部分系统上电（规格书定义真正上电开始是自检后）计时的依据，不能用于长期累加计时.
extern volatile unsigned int zq_timer_s;			// 主任务循环前开始计时, 1s精度, 基于高速时钟。主循环前会清零,
extern volatile unsigned int zq_timer_rtc_s;		// 上电初始化计时器开始计时, 约1s精度, 单位1s, 上电后不会清零, 基于内部RC低速时钟。用于1. 休眠24小时唤醒计时, 2. 系统总运行时间
extern volatile unsigned int zq_timer_rtc_s_pow;	// 上电初始化计时器开始计时(唤醒后会清零, 只有normal模式使用, 自检后清零开始计数), 单位1s, 基于内部RC低速时钟。用于1. 判断上电(首次和唤醒)
extern volatile unsigned int zq_rtc_wdt_10s;		// 休眠时候WDG基于高速系统时钟，无法使用，使用RTC定时器模拟一个10s的watchdog
extern volatile unsigned int hal_battery_plus;  	// 电池侦测计数

// general fucntion declare ----------------------------------------------------------------------------------------
extern void ZqInitMsgQueue(void);
extern void zqPostMessage(ZqMessage msg);
extern int ZqGetMessage(ZqMessage *pmsg);
extern int round_10(int num);

extern short ZyAverageShort(short *pv, uint8_t n);
extern void M0DelayMs(int ms);



extern ZqRingBuf *ZqRingBufCreate(uint8_t *org_buf, int len);
extern int ZqRingBufSize(ZqRingBuf *prb);
extern int ZqRingBufDateSize(ZqRingBuf *prb);
extern void ZqRingBufFlush(ZqRingBuf* prb, int len);
extern int ZqRingBufWrite(ZqRingBuf *prb, const uint8_t *buf, int len);
extern int ZqRingBufTryRead(ZqRingBuf *prb, uint8_t *buf, int len);
extern int ZqRingBufRead(ZqRingBuf *prb, uint8_t *buf, int len);
extern uint32_t ZqmGetSysTimestamp(void);
extern void ZqmGetSysTime(uint16_t *py, uint16_t *pmon, uint16_t *pd, uint16_t *ph, uint16_t *pm, uint16_t *ps);
extern bool ZqmCaliSysTime(uint32_t new_stamp);

#ifdef ZQ_SIMULATOR
#include "simu_mcu582.h"
#endif
